package com.winchain.chainbill.asset.biz.credit.service.impl;

import com.shell.bee.acct.AcctException;
import com.shell.bee.acct.transaction.po.AcctTxRec;
import com.shell.bee.acct.transaction.vo.AcctInfo;
import com.shell.bee.base.exception.UnCheckMsgException;
import com.shell.constant.rel.AssetCode;
import com.shell.framework.utils.CommonDataUtil;
import com.shell.stellar.StellarConfiguration;
import com.winchain.chainbill.ChainBillUtil;
import com.winchain.chainbill.asset.biz.credit.AssetEvent;
import com.winchain.chainbill.asset.biz.credit.rx.AssetTranSubscriber;
import com.winchain.chainbill.asset.biz.credit.service.AssetsMgtService;
import com.winchain.chainbill.trade.service.BillAcctService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import rx.Observable;

@Service("assetsMgtService")
public class AssetsMgtServiceImpl implements AssetsMgtService {
	@Autowired
	private AssetTranSubscriber assetTranSubscriber;
	@Autowired
	private BillAcctService billAcctService;

	public String issue(BigDecimal crAssert, BigDecimal rvAssert) {
		String cusId = CommonDataUtil.getCurEntId();
		List<AcctTxRec> list = new ArrayList(2);
		AcctTxRec crTx = getTxRec(crAssert, "dist_cred", cusId);
		list.add(crTx);

		AcctInfo acctInfo = new AcctInfo();

		acctInfo.setAcctType("2");
		acctInfo.setCurrCode(AssetCode.XCB.name());
		acctInfo.setCustId(cusId);
		acctInfo = this.billAcctService.getAcctInfo(acctInfo);
		if ((null != acctInfo) && (null != acctInfo.getAcctAmt())
				&& (acctInfo.getAcctAmt().compareTo(new BigDecimal(0)) <= 0)) {
			AcctTxRec tsTx = getTxRec(new BigDecimal(StellarConfiguration.getIssueAssetChain()), "dist_trans", cusId);
			list.add(tsTx);
		}
		AssetEvent<AcctTxRec> event = new AssetEvent();
		event.setRecords(list);

		Observable<AssetEvent<AcctTxRec>> observers = Observable.just(event);

		observers.subscribe(this.assetTranSubscriber);
		if (ChainBillUtil.onChain()) {
			Object txSnHost = event.getValue("txSnHost");
			if (txSnHost != null) {
				return (String) txSnHost;
			}
		}
		return null;
	}

	private AcctTxRec getTxRec(BigDecimal amt, String bizType, String cusId) {
		String optType = "qt_inc";

		AcctTxRec txRec = new AcctTxRec();
		txRec.setTxAmt(amt);
		txRec.setTxType(bizType);
		txRec.setOptType(optType);
		txRec.setBizId(cusId);

		return txRec;
	}

	public String adjust(BigDecimal crAssert, BigDecimal rvAssert) {
		String cusId = CommonDataUtil.getCurEntId();

		List<AcctTxRec> list = new ArrayList(2);
		AcctTxRec crTx = getTxRec4Adjust(crAssert, "1", AssetCode.XQT.name(), "adj_cred", cusId);
		if (crTx != null) {
			list.add(crTx);
		}
		if (checkAssertAmt(crAssert)) {
			throw new UnCheckMsgException("����������������������������������������������");
		}
		AssetEvent<AcctTxRec> event = new AssetEvent();
		event.setRecords(list);
		event.setFinRecords(null);

		Observable<AssetEvent<AcctTxRec>> observers = Observable.just(event);

		observers.subscribe(this.assetTranSubscriber);
		if (ChainBillUtil.onChain()) {
			Object txSnHost = event.getValue("txSnHost");
			if (txSnHost != null) {
				return (String) txSnHost;
			}
		}
		return null;
	}

	private boolean checkAssertAmt(BigDecimal crAssert) {
		String finId = CommonDataUtil.getCurEntId();
		AcctInfo fAcct = getAcctBas(finId, "1", AssetCode.XQT.name());
		BigDecimal oldCrAmt = fAcct.getAcctAmt();
		BigDecimal surplusAmt = fAcct.getAcctBlc().subtract(fAcct.getAcctBlk()).add(crAssert.subtract(oldCrAmt));
		return surplusAmt.compareTo(BigDecimal.ZERO) < 0;
	}

	private AcctInfo getAcctBas(String cusId, String acctType, String currCode) {
		AcctInfo acct = new AcctInfo();
		acct.setCustId(cusId);
		acct.setAcctType(acctType);
		acct.setCurrCode(currCode);
		acct = this.billAcctService.getAcctInfo(acct);
		if (acct == null) {
			throw new AcctException(cusId + "-" + acctType + "����������");
		}
		return acct;
	}

	private AcctTxRec getTxRec4Adjust(BigDecimal amtchange, String acctType, String currCode, String bizType,
			String cusId) {
		String optType = "qt_inc";
		BigDecimal txAmt = new BigDecimal(0);

		AcctInfo acctInfo = new AcctInfo();
		acctInfo.setCustId(cusId);
		acctInfo.setAcctType(acctType);
		acctInfo.setCurrCode(currCode);
		acctInfo = this.billAcctService.getAcctInfo(acctInfo);

		BigDecimal amt = acctInfo.getAcctAmt();
		if (amt.compareTo(amtchange) < 0) {
			txAmt = amtchange.subtract(amt);
		} else if (amt.compareTo(amtchange) > 0) {
			optType = "qt_red";
			txAmt = amt.subtract(amtchange);
		} else {
			txAmt = new BigDecimal(0);
			return null;
		}
		AcctTxRec txRec = new AcctTxRec();
		txRec.setTxAmt(txAmt);
		txRec.setTxType(bizType);
		txRec.setOptType(optType);
		txRec.setBizId(cusId);

		return txRec;
	}
}
